#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include "log.h"
#include <errno.h>
#include <string.h>
#include <stdint.h>


#define LOG_RUN_LEVEL LOG_LEVEL_INFO

int copy_file(const char *src,const char *dest)
{
    FILE *src_file = fopen(src,"r");
    if(src_file == NULL){
        LOG_E("not find copy source file");
        return -1; 
    }

    FILE *dst_file = fopen(dest,"w+");
    if(dst_file == NULL){
        LOG_E("not create copy destination file");
        return -2; 
    }

    fseek(src_file,0,SEEK_END);
    int src_size = ftell(src_file);
    char *buf = malloc(src_size);
    if(buf == NULL){
        LOG_E("malloc err");
        return -3; 
    }
    fseek(src_file,0,SEEK_SET);
    fread(buf,1,src_size,src_file);
    fwrite(buf,1,src_size,dst_file);

    free(buf);

    fclose(src_file);
    fclose(dst_file);
}

int move_file(const char *src,const char *dest)
{
    int rc = 0; 
    do{
        LOG_D("ready copy srcfile:%s,dstfile:%s",src,dest);

        rc = copy_file(src,dest);
        if(rc){
            LOG_E("move file err,rc:%d",rc);
            break; 
        }
        rc = remove(src);
        if(rc){
            LOG_E("remove file err,rc:%d",rc);
            break; 
        }

    }while(0);

    return (rc);
}


int file_merge(char *file1_path,char *file2_path,uint32_t file2_offset,char *dstfile_path)
{
    /*file_1*/
    if(file1_path == NULL){
        LOG_E("file1 path is null");
        return -1; 
    }
    FILE *sfile1 = fopen(file1_path,"rb");
    if(sfile1 == NULL){
        LOG_E("can not open the file:%s",file1_path);
        return -1; 
    }
    LOG_D("open %s",file1_path);

    /* file_2 */
    if(file2_path == NULL){
        LOG_E("file2 path is null");
        return (-1);
    }
    FILE *sfile2 = fopen(file2_path,"rb");
    if(sfile2 == NULL){
        LOG_E("can not open the file:%s",file2_path);
        return -1; 
    }
    LOG_D("open %s",file2_path);

    /*file_3*/
    FILE *dfile = fopen(dstfile_path,"wb+");
    if(dfile == NULL){
        LOG_E("can not open the file:%s",dstfile_path);
        perror("reason:");
        return -1; 
    }
    LOG_D("open %s",dstfile_path);

    /* copy file_1*/
    uint8_t buf[1024] = {0}; 
    int loop; 
    fseek(sfile1,0,SEEK_END);
    int filesize = ftell(sfile1);
    LOG_D("file size:%d",filesize);
    fseek(sfile1,0,SEEK_SET);

    while(!feof(sfile1)){
        memset(buf,0,sizeof(buf));
        fread(buf,sizeof(buf),1,sfile1); 

        fwrite(buf,sizeof(buf),1,dfile);
    }
    fclose(sfile1); 

    fseek(dfile,file2_offset,SEEK_SET);

    /* copy file_2*/
    fseek(sfile2,0,SEEK_END);
    filesize = ftell(sfile2);
    LOG_D("file size:%d",filesize);
    fseek(sfile2,0,SEEK_SET);

    while(!feof(sfile2)){
        memset(buf,0,sizeof(buf));
        fread(buf,sizeof(buf),1,sfile2); 

        fwrite(buf,sizeof(buf),1,dfile);

    }
    fclose(sfile2);


    fclose(dfile);

    return (0);
}


static void delete_config(const char *Dir)
{
    do{
        DIR *dir = opendir(Dir); 
        if(dir == NULL){
            LOG_E("delete ini.bin file error");
            break; 
        }

        struct dirent *rent;
        char path[128] = {0};
        while((rent = readdir(dir)) != NULL){  
            LOG_D("read file:%s",rent->d_name);
            if(strstr(rent->d_name,".ini.bin") != NULL){
                memset(path,0,sizeof(path));
                snprintf(path,sizeof(path),"%s\\%s",Dir,rent->d_name);
                LOG_D("remove file:%s",path);
                remove(path); 
            }
        }
        closedir(dir);

    }while(0); 
}

/*
 * 思路：   
 *      通过bat脚本传入参数：./main.exe 芯片系列号 bootloader.bin   app.bin  app_offset   config_offset
 * 
 * 在exe文件中将bootloader + app + config合成一个bin文件
 */
int main(int argc,char **argv)
{
    int rc = 0; 
 
    int loop; 
    for(loop=1;loop<argc;loop++){
        LOG_I("Parmeter[%d]:%s",loop,argv[loop]);
    }
    
    if(argc != 6){
        LOG_E("The Parameter is error");
        return -1; 
    }

    delete_config("..\\fireware");

    char *license_path = "..\\license"; 
    DIR *dir = opendir(license_path); 
    if(dir == NULL)
    {
        LOG_E("Not Open License Dir");
        return -1; 
    }

    struct dirent *rent;
    while((rent = readdir(dir)) != NULL){
        if(rent->d_name[0] == '.'){
            rc = -1; 
            continue; 
        }
            
        if(strstr(rent->d_name,"history") != NULL){
            rc = -1; 
            continue;
        }
             
        LOG_I("find a license file:%s",rent->d_name);

        if(strstr(rent->d_name,".ini") != NULL)
        {
            char src_path[64] = "..\\license\\";
            strcat(src_path,rent->d_name);

            char cof_name[128] = {0};
            char his_path[128] = {0};
            snprintf(cof_name,sizeof(cof_name),"..\\fireware\\%s.bin",rent->d_name);
            snprintf(his_path,sizeof(his_path),"..\\license\\history\\%s",rent->d_name);

            rc = copy_file(src_path,cof_name);
            if(rc){
                LOG_E("copy config file err,rc:%d",rc);
                break; 
            }

            rc = file_merge(argv[2],argv[3],strtoul(argv[4],NULL,16),"..\\fireware\\s1.bin");
            if(rc){
                LOG_E("merge file err,rc:%d",rc);
                break; 
            }

            rc = file_merge("..\\fireware\\s1.bin",cof_name,strtoul(argv[5],NULL,16),"..\\fireware\\fireware.bin");
            if(rc){
                LOG_E("merge file err,rc:%d",rc);
                break; 
            }
            remove("..\\fireware\\s1.bin");

            rc = move_file(src_path,his_path);
            if(rc){
                LOG_E("generate history file err,rc:%d",rc); 
                break; 
            }

            LOG_I("Generate New FireWare Success!!!!!!!");
            break; 
        }
    }

    closedir(dir);
    
    return rc; 
}